查看原文
其他

Linux 中的软件安装进度条怎么搞?

点击上方 "Linux就该这样学关注,星标或者置顶,第一时间送达

责编:Linux妹 | 来源:入门小站

上一篇:致力推广 Vim 的那个程序员走了,Vim 之父:我要把 9.0 版献给他

大家好,我是Linux妹。

我们在平时的服务器运维工作中,要经常安装一些软件,经常会看到下面这种进度条,本文就用C语言来实现这种进度条。

一、回车与换行

换行是换到下一行的当前位置,一般用\n表示。回车是回到当前行的开始,一般用\r表示。

但一般在语言,比如C语言中,用\n代表换行+回到开始。

二、缓冲区

先来看两段代码及其现象。

第一段代码,代码很简单,主要是为了与第二段形成对比。

#include <stdio.h>                                                                                         
#include <unistd.h>   
  
int main()                                                                                         
{                                                                                         
  printf("I am a proc\n");//有\n  
  sleep(3);                                                                                                                                                                
  return 0;                                                                                
}  

先打印,再sleep持续3秒,很自然的结果。

第二段代码:

#include <stdio.h>                                                                                         
#include <unistd.h>   
  
int main()                                                                                         
{                                                                                         
  printf("I am a proc");//没有\n  
  sleep(3);                                                                                                                                                                
  return 0;                                                                                
}  

第二段代码运行结果如下,从结果看来是先sleep持续3s,然后才打印。

事实上,上面的代码中由于printf在sleep之前,所以printf永远先于sleep执行,但是先执行printf不代表先打印。

printf执行后,要打印的内容放入缓冲区,但不一定会被立即刷新到屏幕上。

这里要提一下缓冲区的3种缓冲策略:

  • 1.无缓冲:数据不缓冲,直接打印到外设中(屏幕、磁盘等等)。

  • 2.行缓冲:先保存一行数据,后续刷新时按行刷新(遇到\n就把前面的内容刷新到外设)。另外,搜索公众号Linux就该这样学后台回复“Linux”,获取一份惊喜礼包。

  • 3.全缓冲:直到把缓冲区全放满才会刷新。

再结合上面两段代码及现象,可以得出上面打印时采用的是行缓冲(遇到\n就把要打印的内容打印在屏幕上)。

三、倒计时的程序

如果每次打印完都回车,就相当于在第一个位置打印一个数字后,又回到该位置,继续打印下一个数字。这样就可以实现倒计时的效果。

#include <stdio.h>                                                                                         
#include <unistd.h>   
  
int main()  
{  
  int count = 3;  
  while(count >= 0)  
  {  
    printf("%d\r", count--);  
    sleep(1);                                                                                                                                                              
  }                                                                                                                                        
  return 0;                                                                                                                                
}  

但结果如下,并没有打印结果,想到行缓冲的规则,原来是因为打印的内容一直都没有换行,所以内容一直存在缓冲区内,不会打印出来。

这里可以用fflush函数强行让屏幕刷新,就可以实现想要的效果了。使用fflush刷新stdout(即屏幕的文件流),使每次进入缓冲区的内容被立即打印出来。看看人家那远程控制系统,那叫一个优雅(附源码)!

#include <stdio.h>                                                                                         
#include <unistd.h>   
  
int main()  
{  
  int count = 3;  
  while(count >= 0)  
  {  
    printf("%d\r", count--);  
    fflush(stdout);  
    sleep(1);                                                                                                                                                              
  }                                                                                                                                        
  return 0;                                                                                                                                
}  

效果如下

但如果是两位或更多位的倒计时,就会出现如下的问题:

#include <stdio.h>                                                                                         
#include <unistd.h>   
  
int main()  
{  
  int count = 10;  
  while(count >= 0)  
  {  
    printf("%d\r", count--);  
    fflush(stdout);  
    sleep(1);                                                                                                                                                              
  }                                                                                                                                        
  return 0;                                                                                                                                
}  

因为每次回车都回到第一个字符,所以第二位的0一直没有改变。

只需用printf的格式控制即可。

#include <stdio.h>                                                                                         
#include <unistd.h>   
  
int main()  
{  
  int count = 10;  
  while(count >= 0)  
  {  
    //控制输出两位字符  
    printf("%2d\r", count--);  
    fflush(stdout);  
    sleep(1);                                                                                                                                                              
  }                                                                                                                                        
  return 0;                                                                                                                                
}  

运行效果如下:

四、进度条程序

#include <stdio.h>    
#include <string.h>    
#include <unistd.h>    
    
void ProcBar()    
{    
  int i = 0;    
  char proc[102];  
  memset(proc, '\0', sizeof(proc));    
    
  while(i <= 100)    
  {  
   //C语言格式控制时默认右对齐,所以要在前面加-变成左对齐    
    printf("[%-100s] [%d%%]\r", proc, i);                                                                                                                                  
    fflush(stdout);//刷新屏幕打印  
    proc[i] = '#';  
    usleep(100000);//以微秒为单位的sleep  
    i++;  
  }  
  printf("\n");  
}                                                                                                                                                   
                                                                                                                                             
int main()                                                                                                                                   
{                                                                                                                                            
  ProcBar();                                                                                                                              
  return 0;                                                                                                                              
}  

  声明:本文部分素材转载自互联网,如有侵权立即删除 。

END


往日精彩:

重磅!阿里发布全新操作系统,能不能干翻 CentOS 呢!

Tabby:一款超高颜值的终端工具(开源免费,全平台支持)

看看人家那远程控制系统,那叫一个优雅(附源码)!

适合程序员的5款Linux发行版

19 个高逼格 Linux 命令,赶紧拿去用!

14家互联网公司裁员(1-2月裁员清单)

妙啊!巧用 SSH 突破限制穿透内网

30 张图详解操作系统总结!

一个很酷的数据可视化大屏系统

再见 CentOS 8/6!来试试这些最佳替代方案吧

喜欢本文的朋友们,欢迎长按二维码,关注订阅号Linux就该这样学


收看更多精彩内容

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存